# _*_ coding:utf-8 _*_
# @Time  : 2023.04.07
# @Author: zizlee
""" 投资计划 """
import datetime
import pathlib

from fastapi import APIRouter, Header, Body, Query, Form, UploadFile, BackgroundTasks
from pydantic import BaseModel, constr, validator
from hutool import security
from db import FAConnection
from v1_all_api.all_response import AllResponse
from v1_all_api.all_utils import datetime_utils, file_utils
from configs import FILE_STORAGE, STATIC_FILE_HOST
from logger import logger

from . import handler_utils


investment_plan_api = APIRouter()
MODULE_NAME = 'InvestmentPlan'
SPECIAL_WORK_TAG = 'T00'
# ---------------------------------- 函数任务 ---------------------


# 记录任务，添加到非常态工作记录中
def add_work_record(rid):
    insert_sql = """
        INSERT INTO work_special_task (user_id,create_date,title,task_type,sponsor,applicant,phone,
        swiss_coin,allowance,partner,note,score,annex,annex_url,prse_id,prse_module)
        VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);
    """
    update_sql = """
        
    """

    with FAConnection() as cursor:
        # 查询该ID的记录信息
        cursor.execute("""
            SELECT a.*,u.admin_name FROM prse_investment_plan As a INNER JOIN ruizy_user As u ON a.creator=u.id WHERE a.id=%s LIMIT 1;
        """, [rid])
        obj = cursor.fetchone()
        if not obj:
            return False
        # 查询该ID是否被添加进了记录
        cursor.execute('SELECT id FROM work_special_task WHERE prse_id=%s AND prse_module=%s LIMIT 1;', [rid, MODULE_NAME])
        task_obj = cursor.fetchone()
        if task_obj:  # 更新记录
            update_prm = [obj['evaluate'], obj['annex_name'], obj['annex'], task_obj['id']]
            uc = cursor.execute('UPDATE work_special_task SET score=%s,annex=%s,annex_url=%s WHERE id=%s LIMIT 1;', update_prm)
            if uc < 1:
                logger.warning('疑似更新work_special_task投资计划撰写评分结果出错，更新数: {}'.format(uc))
        else:  # 添加记录
            create_date = obj['annex_time'].strftime('%Y%m%d')
            score = obj['evaluate'] if obj['evaluate'] else 0
            insert_prm = [obj['worker_id'], create_date, obj['variety'] + '投资计划', SPECIAL_WORK_TAG, '', obj['admin_name'],
                          obj['link_msg'], obj['quota'], 0, '', '', score, obj['annex_name'], obj['annex'], rid, MODULE_NAME]
            ic = cursor.execute(insert_sql, insert_prm)
            if ic < 1:
                logger.warning('疑似插入work_special_task投资计划撰写记录结果出错，插入数: {}'.format(ic))
    return True


# ---------------------------------------------------- 前端申请等 -------------------------------------------------------


# 创建项目
class PlanCreatedItem(BaseModel):
    variety: constr(max_length=200)
    fund: constr(max_length=200)
    use_to: constr(max_length=200)
    cycle: constr(max_length=100)
    risk: constr(max_length=200)
    finish_time: str
    link_msg: constr(max_length=300)
    delivery: constr(max_length=300)
    content: constr(max_length=500)

    @validator('finish_time')
    def validate_finish_time(cls, value):
        dt = datetime_utils.auth_datetime_string(value, f='%Y-%m-%d %H:%M:%S')
        if not dt:
            raise ValueError('日期格式错误,接受%Y-%m-%d %H:%M:%S型.')
        return dt


# 评价项目
class PlanEvaluateItem(BaseModel):
    id: int
    evaluate: int
    evaluate_plain: str
    is_anonymous: bool


# 申请者提交一个申请
@investment_plan_api.post('/my/')
def create_investment_plan(ruizy_token: str = Header(...), plan: PlanCreatedItem = Body(...)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    # 检查是否够申请积分
    need_quota, remain_quota = handler_utils.quota_information(module_name=MODULE_NAME, user_id=person['uid'])
    if need_quota > remain_quota:
        return AllResponse.validate_error(msg='申请所需积分为: {}，当前剩余：{}。'.format(need_quota, remain_quota))
    # 将数据保存
    sql = """
      INSERT INTO prse_investment_plan(creator,variety,fund,use_to,cycle,risk,finish_time,link_msg,content,state,quota)
      VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);
    """
    prm = (person['uid'], plan.variety, plan.fund, plan.use_to, plan.cycle, plan.risk,
           plan.finish_time, plan.link_msg, plan.content, 0, need_quota)
    with FAConnection() as cursor:
        c = cursor.execute(sql, prm)
        if c:
            cursor.execute('SELECT LAST_INSERT_ID() AS insertID;')
            insert_id = cursor.fetchone()['insertID']
            # 申请成功，扣取积分
            handler_utils.quota_change_log(user_id=person['uid'], prse_id=insert_id, cursor=cursor,
                                           change=need_quota, module_key=MODULE_NAME)
    return AllResponse.create_successfully(msg='提交成功，请前往记录查看.') if c else AllResponse.server_error()


@investment_plan_api.get('/my/')
def query_my_investment_plan(ruizy_token: str = Header(...),
                             page: int = Query(...), page_size: int = Query(...)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    # 查询自己的申请记录
    sql = """
      SELECT * FROM prse_investment_plan WHERE creator=%s ORDER BY create_time DESC;
    """
    db_conn = FAConnection()
    ret = db_conn.query_paginator(sql, [person['uid']], page=page, page_size=page_size)
    states = {
        -1: '拒绝',
        0: '等待中',
        1: '进行中',
        2: '完成'
    }
    for row in ret['data']:
        row['create_time'] = datetime_utils.to_string(row['create_time'], is_time=True)
        row['finish_time'] = datetime_utils.to_string(row['finish_time'], is_time=True)
        row['state_text'] = states.get(row['state'], '未知')
        row['annex_public'] = True if row['annex_public'] else False
        if row['annex'] and row['annex_public']:
            row['has_annex'] = True
            row['annex_url'] = STATIC_FILE_HOST + row['annex']
        else:
            row['annex_url'] = ''
            row['annex_name'] = '无'
            row['has_annex'] = False
        del row['annex']
    return AllResponse.operate_successfully(data=ret)


# 对一个申请结果评价
@investment_plan_api.post('/myEvaluate/')
def evaluate_investment_plan(ruizy_token: str = Header(...), evaluate: PlanEvaluateItem = Body(...)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    # 检查是否评价过了
    sql = """
      UPDATE prse_investment_plan SET evaluate=%s,evaluate_plain=%s,is_anonymous=%s WHERE id=%s AND creator=%s LIMIT 1;
    """
    prm = (evaluate.evaluate, evaluate.evaluate_plain, evaluate.is_anonymous, evaluate.id, person['uid'])
    with FAConnection() as cursor:
        cursor.execute('SELECT id,evaluate,annex_name,annex,annex_public FROM prse_investment_plan WHERE id=%s AND creator=%s LIMIT 1;',
                       (evaluate.id, person['uid']))
        obj = cursor.fetchone()
        if not obj:
            return AllResponse.no_do_anything(msg='未检测到该条数据，评价失败.')
        if obj['evaluate'] and obj['evaluate'] > 0:
            return AllResponse.validate_error(msg='您已经评价过，无需重复评价.')
        cursor.execute(sql, prm)
    add_work_record(evaluate.id)
    # 返回附件地址
    annex_url = ''
    if obj['annex'] and obj['annex_public']:
        annex_url = STATIC_FILE_HOST + obj['annex']
    return AllResponse.operate_successfully(msg='评价成功', data={
        'evaluate': evaluate.evaluate, 'id': evaluate.id, 'annex_url': annex_url,
        'has_annex': True if annex_url else False
    })


# 预览材料文件
@investment_plan_api.get('/my/dataPreView/')
def preview_investment_plan(ruizy_token: str = Header(...), rid: int = Query(...)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    # 查询数据资料
    with FAConnection() as cursor:
        cursor.execute('SELECT id,variety,annex FROM prse_investment_plan WHERE id=%s LIMIT 1;', (rid, ))
        obj = cursor.fetchone()
        if not obj:
            return AllResponse.server_no_content(msg='数据不存在')
    if not obj['annex']:
        return AllResponse.validate_error('还没有资料文件')
    # 资料文件
    annex_file = pathlib.Path(FILE_STORAGE).joinpath(obj['annex'])
    if not annex_file.exists():
        return AllResponse.server_no_content(msg='数据资料不存在')
    # 读取预览图片文件
    preview_folder = annex_file.parent.joinpath(annex_file.name + 'img')
    if preview_folder.exists() and not preview_folder.is_file():
        # 存在着预览的图片文件，读取文件信息
        if annex_file.name.endswith('.ppt') or annex_file.name.endswith('.pptx'):
            images = file_utils.get_file_list(preview_folder, glob='*.jpg', replaces=['幻灯片', '.JPG'])
        else:
            images = file_utils.get_file_list(preview_folder, glob='*.png')
    else:
        # 不存在，就得转化
        images = handler_utils.covert_file2image(annex_file)
        if len(images) < 1:
            return AllResponse.validate_error(msg='不支持预览的资料')
    images = [str(i).replace('\\', '/').replace(FILE_STORAGE, STATIC_FILE_HOST) for i in images]
    return AllResponse.operate_successfully(data={
        'id': rid,
        'topic': obj['variety'],
        'images': images
    })


# ---------------------------------------------------- 管理员处理 -------------------------------------------------------


# 管理员查询
@investment_plan_api.get('/manage/')
def query_lecture_train(ruizy_token: str = Header(...), page: int = Query(1), page_size: int = Query(30), state: int = Query(0)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    if not security.operator_is_manager(person):
        return AllResponse.forbidden_error()
    sql = """
        SELECT a.*,u.admin_name FROM prse_investment_plan As a INNER JOIN ruizy_user As u ON a.creator=u.id
        WHERE a.state=%s ORDER BY a.create_time DESC;
    """
    db_conn = FAConnection()
    ret = db_conn.query_paginator(sql, [state], page=page, page_size=page_size)
    states = {
        -1: '拒绝',
        0: '等待',
        1: '通过',
        2: '完成'
    }
    for row in ret['data']:
        row['create_time'] = datetime_utils.to_string(row['create_time'], is_time=True)
        row['finish_time'] = datetime_utils.to_string(row['finish_time'], is_time=True)
        row['state_text'] = states.get(row['state'], '未知')
        if row['annex']:
            row['annex_url'] = STATIC_FILE_HOST + row['annex']
            del row['annex']
    return AllResponse.operate_successfully(data=ret)


class DispatchModel(BaseModel):
    rid: int
    worker_id: int
    state: int
    explain_state: str


# 管理员分配任务
@investment_plan_api.post('/manage/')
def dispatch_lecture_train(ruizy_token: str = Header(...), dispatch_item: DispatchModel = Body(...)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    if not security.operator_is_manager(person):
        return AllResponse.forbidden_error()
    now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    sql = "UPDATE prse_investment_plan SET state=%s,state_plain=%s,worker_id=%s,dispatch_time=%s WHERE id=%s LIMIT 1;"
    prm = [dispatch_item.state, dispatch_item.explain_state, dispatch_item.worker_id, now_time, dispatch_item.rid]
    with FAConnection() as cursor:
        cursor.execute('SELECT * FROM prse_investment_plan WHERE id=%s LIMIT 1;', [dispatch_item.rid])
        _obj = cursor.fetchone()
        if not _obj:
            return AllResponse.validate_error(msg='处理的记录不存在!')
        cursor.execute(sql, prm)  # 执行更新
        if dispatch_item.state == -1:  # 当拒绝时应加回积分
            handler_utils.quota_change_log(user_id=person['uid'], prse_id=dispatch_item.rid, cursor=cursor,
                                           change=-_obj['quota'], module_key=MODULE_NAME)
    return AllResponse.operate_successfully(msg='处理申请记录成功!')


# 将任务手动添加到【非常规工作中】中
@investment_plan_api.post('/manage/addSpecialWork/')
def active_add_special_work(ruizy_token: str = Header(...), rid: int = Query(...)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    if not security.operator_is_manager(person):
        return AllResponse.forbidden_error()
    # 添加一条路演记录，类型和规模按line和scale字段名内外培训。此功能在相关任务人员上传材料时也有实现
    success = add_work_record(rid)
    msg = '添加非常规工作记录成功！' if success else '记录不存在,添加失败!'
    return AllResponse.operate_successfully(msg=msg)

# ---------------------------------------------------- 任务员处理 -------------------------------------------------------


# 人员查询自己的任务
@investment_plan_api.get('/worker/')
def query_lecture_train_tome(ruizy_token: str = Header(...), page: int = Query(1), page_size: int = Query(30), state: int = Query(0)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    sql = """
        SELECT a.*,u.admin_name FROM prse_investment_plan As a INNER JOIN ruizy_user As u ON a.creator=u.id
        WHERE a.state=%s AND a.worker_id=%s ORDER BY a.create_time DESC;
    """
    db_conn = FAConnection()
    ret = db_conn.query_paginator(sql, [state, person['uid']], page=page, page_size=page_size)
    states = {
        1: '待处理',
        2: '已完成'
    }
    for row in ret['data']:
        row['create_time'] = datetime_utils.to_string(row['create_time'], is_time=True)
        row['finish_time'] = datetime_utils.to_string(row['finish_time'], is_time=True)
        row['state_text'] = states.get(row['state'], '未知')
        if row['annex']:
            row['annex_url'] = STATIC_FILE_HOST + row['annex']
            del row['annex']
    return AllResponse.operate_successfully(data=ret)


# 人员上传附件材料
@investment_plan_api.post('/worker/')
async def finish_lecture_train_tome(bg_tasks: BackgroundTasks, ruizy_token: str = Header(...),
                                    rid: int = Form(...), annex_public: bool = Form(False), annex: UploadFile = Form(...)):
    person = security.decrypt_access_token(ruizy_token)
    if not person:
        return AllResponse.no_authorization()
    # 写入文件
    save_path, sql_path = file_utils.get_file_paths(module_name='ProductService/InvestmentPlan', filename=annex.filename,
                                                    hashed=True)
    annex_content = await annex.read()
    with open(save_path, 'wb') as fp:
        fp.write(annex_content)
    # 更新数据
    now_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    annex_public = 1 if annex_public else 0
    sql = "UPDATE prse_investment_plan SET annex_name=%s,annex_time=%s,annex=%s,annex_public=%s,state=2 WHERE id=%s LIMIT 1;"
    prm = [annex.filename, now_time, sql_path, annex_public, rid]
    with FAConnection() as cursor:
        cursor.execute(sql, prm)
    # 添加非常规工作记录
    bg_tasks.add_task(add_work_record, rid)
    bg_tasks.add_task(handler_utils.covert_file2image, pathlib.Path(save_path))  # 后台任务转为图片
    return AllResponse.operate_successfully(msg='上传附件材料成功!')

